package com.yuejie.musicai.services.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.yuejie.musicai.beans.UrlParsed;
import com.yuejie.musicai.controller.AccountController;
import com.yuejie.musicai.services.ParseUrlService;


/**
* @author leilz
* @date 2012-6-28
*/
@Service
public class ParseUrlServiceImpl implements ParseUrlService{
	private Logger logger = LoggerFactory.getLogger(AccountController.class);
	
	@Override
	public UrlParsed getUrlXml(String url){
		
		UrlParsed urlParsed = new UrlParsed();
		List<String[]> realUrlList;
		try {
			realUrlList = this.getRealUrlList(url);
			List<String> flvlist = new ArrayList<String>();
			List<String> hdlist = new ArrayList<String>();
			List<String> hd2list = new ArrayList<String>();
			String[] flvUrls = realUrlList.get(0);
			for(String flvUrl : flvUrls){
				flvlist.add(flvUrl);
			}
			String[] hdUrls = realUrlList.get(1);
			for(String hdUrl : hdUrls){
				hdlist.add(hdUrl);
			}
			String[] hd2Urls = realUrlList.get(2);
			for(String hd2Url : hd2Urls){
				hd2list.add(hd2Url);
			}
			urlParsed.setNormal(flvlist);
			urlParsed.setHd(hdlist);
			urlParsed.setUltrahd(hd2list);
			
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		return urlParsed;
	}
	
	/**
	 * <p>
	 * 获取返回的json
	 * </p>
	 * 
	 * @param requestUrl
	 * @return
	 */
	private String getJsonStr(String requestUrl) {
		URL url = null;
		HttpURLConnection conn = null;
		BufferedReader br = null;
		String s = "";
		StringBuffer sb = new StringBuffer("");

		try {
			url = new URL(requestUrl);
			conn = (HttpURLConnection) url.openConnection();
			conn.setInstanceFollowRedirects(false);
			conn.connect();
			int httpStatus = conn.getResponseCode();
			if (httpStatus != HttpURLConnection.HTTP_OK) {
				logger.warn(requestUrl + ":状态码-" + httpStatus);
			} else {
				br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
				while ((s = br.readLine()) != null) {
					sb.append(s + "\r\n");
				}
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			logger.warn("打开给定url连接失败,url=" + requestUrl);
			e.printStackTrace();
		}
		String responseStr = sb.toString();
		responseStr = responseStr.substring(0, responseStr.lastIndexOf("\r\n"));
		return responseStr;
	}

	/**
	 * <p>
	 * 获取真实视频地址
	 * </p>
	 * 
	 * @param seed
	 * @param objFields
	 * @param objSegs
	 * @param sid
	 * @param format
	 * @return
	 * @throws JSONException
	 */
	private String[] getRealUrl(double seed, JSONObject objFields, JSONObject objSegs, String sid,
			String format) throws JSONException {
		String[] realUrl = null;
		String fileId = "";
		if (format.equals("hd2")) {
			try {
				fileId = objFields.getString("hd2");
			} catch (JSONException e1) {
				return new String[] {};
			}
		} else if (format.equals("mp4")) {
			try {
				fileId = objFields.getString("mp4");
			} catch (JSONException e1) {
				return new String[] {};
			}
		} else {
			try {
				fileId = objFields.getString("flv");
			} catch (JSONException e1) {
				return new String[] {};
			}
		}

		String realFileid = getRealFieldID(fileId, seed);

		String fieldIdLeft = realFileid.substring(0, 8);
		String fieldIdRight = realFileid.substring(10);

		JSONArray formatArray = objSegs.getJSONArray(format);
		realUrl = new String[formatArray.length()];
		if (format.equals("hd2")) {
			format = "flv";
		}
		for (int i = 0; i < formatArray.length(); i++) {
			JSONObject o = formatArray.getJSONObject(i);
			String k = o.getString("k");
			realUrl[i] = "http://f.youku.com/player/getFlvPath/sid/" + sid + "_"
					+ String.format("%1$02X", i) + "/st/" + format + "/fileid/" + fieldIdLeft
					+ String.format("%1$02X", i) + fieldIdRight + "?K=" + k;
		}

		return realUrl;
	}

	/**
	 * <p>
	 * 获取全部真实视频地址,普通、高清、超清
	 * </p>
	 * 
	 * @param jsonStr
	 * @return
	 * @throws JSONException
	 */
	private List<String[]> getRealUrlList(String requestUrl) throws JSONException {
		String vid = requestUrl.substring(requestUrl.indexOf("id_") + 3,
				requestUrl.indexOf(".html"));
		String reqJsonUrl = "http://v.youku.com/player/getPlayList/VideoIDS/" + vid;
		String jsonStr = getJsonStr(reqJsonUrl);

		List<String[]> realUrlList = new LinkedList<String[]>();
		JSONObject jsonObj = new JSONObject(jsonStr);
		JSONArray jsonArray = jsonObj.getJSONArray("data");
		JSONObject objTop = jsonArray.getJSONObject(0);

		double seed = objTop.getDouble("seed");
		JSONObject objFields = objTop.getJSONObject("streamfileids");
		JSONObject objSegs = objTop.getJSONObject("segs");

		String sid = generateSid();

		String[] flvStrArray = getRealUrl(seed, objFields, objSegs, sid, "flv");
		String[] mp4StrArray = getRealUrl(seed, objFields, objSegs, sid, "mp4");
		String[] hd2StrArray = getRealUrl(seed, objFields, objSegs, sid, "hd2");
		realUrlList.add(flvStrArray);
		realUrlList.add(mp4StrArray);
		realUrlList.add(hd2StrArray);

		return realUrlList;
	}

	/**
	 * <p>
	 * 生成sid
	 * </p>
	 * 
	 * @return
	 */
	private String generateSid() {
		int i1 = (int) (1000 + Math.floor(Math.random() * 999));
		int i2 = (int) (1000 + Math.floor(Math.random() * 9000));
		return System.currentTimeMillis() + "" + i1 + "" + i2;
	}

	private String getRealFieldID(String fileId, double seed) {
		String mixed = getFieldIDMixString(seed);
		String[] ids = fileId.split("\\*");
		StringBuilder realId = new StringBuilder();
		int idx;
		for (int i = 0; i < ids.length; i++) {
			idx = Integer.parseInt(ids[i]);
			realId.append(mixed.charAt(idx));
		}
		return realId.toString();
	}

	private String getFieldIDMixString(double seed) {
		StringBuilder mixed = new StringBuilder();
		StringBuilder source = new StringBuilder(
				"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\\:._-1234567890");
		int index, len = source.length();
		for (int i = 0; i < len; ++i) {
			seed = (seed * 211 + 30031) % 65536;
			index = (int) Math.floor(seed / 65536 * source.length());
			mixed.append(source.charAt(index));
			source.deleteCharAt(index);
		}
		return mixed.toString();
	}
}
